package com.franzliszt.professionalcalcuator;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

import java.util.Stack;

public class MainActivity extends AppCompatActivity {
    private TextView  Reset,Zero,ResultBox;
    private BtnCircle mDivision,mAdd,mSub,mMultiply,mMod,mEqual,mPoint;
    private BtnCircle One,Two,Three,Four,Five,Six,Seven,Eight,Nine;
    private StringBuilder numBuilder;
    private boolean isReset = false;
    //是否按等于键
    private boolean isReturn = false;
    private Stack<Double> numStack;
    private Stack<Character> operatorStack;
    public static final char ADD = '+';
    public static final char SUB = '-';
    public static final char MULTIPLY = '*';
    public static final char DIVISION = '/';
    public static final char MOD = '%';
    public static final char EQUAL = '=';


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (Build.VERSION.SDK_INT >= 21) {
            View decorView = getWindow().getDecorView();
            decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );
            getWindow().setStatusBarColor( Color.TRANSPARENT );
        }
        setContentView(R.layout.activity_main);
        InitView();
        InitVar();
        Listener();

    }
    private void InitVar(){
        numStack = new Stack<>();
        operatorStack = new Stack<>();
        numBuilder = new StringBuilder();
        operatorStack.push('#');
    }
    private void InitView(){
        ResultBox = findViewById(R.id.ResultBox);

        Reset = findViewById(R.id.Reset);
        Zero = findViewById(R.id.Zero);

        mAdd = findViewById(R.id.Add);
        mSub = findViewById(R.id.Sub);
        mMultiply = findViewById(R.id.Multiply);
        mDivision = findViewById(R.id.Division);
        mMod = findViewById(R.id.Mod);
        mEqual = findViewById(R.id.Equal);
        mPoint = findViewById(R.id.Point);

        One = findViewById(R.id.One);
        Two = findViewById(R.id.Two);
        Three = findViewById(R.id.Three);
        Four = findViewById(R.id.Four);
        Five = findViewById(R.id.Five);
        Six = findViewById(R.id.Six);
        Seven = findViewById(R.id.Seven);
        Eight = findViewById(R.id.Eight);
        Nine = findViewById(R.id.Nine);

    }
    private void Listener(){
        NumOnClick numOnClick = new NumOnClick();
        Zero.setOnClickListener(numOnClick);
        One.setOnClickListener(numOnClick);
        Two.setOnClickListener(numOnClick);
        Three.setOnClickListener(numOnClick);
        Four.setOnClickListener(numOnClick);
        Five.setOnClickListener(numOnClick);
        Six.setOnClickListener(numOnClick);
        Seven.setOnClickListener(numOnClick);
        Eight.setOnClickListener(numOnClick);
        Nine.setOnClickListener(numOnClick);
        Reset.setOnClickListener(numOnClick);
        mPoint.setOnClickListener(numOnClick);

        OperatorOnClick operatorOnClick = new OperatorOnClick();
        mAdd.setOnTouchListener(operatorOnClick);
        mSub.setOnTouchListener(operatorOnClick);
        mMultiply.setOnTouchListener(operatorOnClick);
        mDivision.setOnTouchListener(operatorOnClick);
        mMod.setOnTouchListener(operatorOnClick);
        mEqual.setOnTouchListener(operatorOnClick);

    }

    public void SwitchView(View view) {
        startActivity(new Intent(MainActivity.this,BinaryConversion.class));
    }

    private class NumOnClick implements View.OnClickListener{
        @Override
        public void onClick(View view) {
            switch (view.getId()){
                case R.id.Zero:
                    numBuilder.append('0');
                    break;
                case R.id.One:
                    numBuilder.append('1');
                    break;
                case R.id.Two:
                    numBuilder.append('2');
                    break;
                case R.id.Three:
                    numBuilder.append('3');
                    break;
                case R.id.Four:
                    numBuilder.append('4');
                    break;
                case R.id.Five:
                    numBuilder.append('5');
                    break;
                case R.id.Six:
                    numBuilder.append('6');
                    break;
                case R.id.Seven:
                    numBuilder.append('7');
                    break;
                case R.id.Eight:
                    numBuilder.append('8');
                    break;
                case R.id.Nine:
                    numBuilder.append('9');
                    break;
                case R.id.Point:
                    numBuilder.append('.');
                    break;
                case R.id.Reset:
                    isReset = true;
            }
            if (isReset){
                PopStack();
                numBuilder.delete(0,numBuilder.length());
                ResultBox.setText("0");
                operatorStack.push('#');
                isReset = false;
            }else {
                ResultBox.setText(numBuilder.toString());
            }

        }
    }
    private class OperatorOnClick implements View.OnTouchListener{

        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            boolean isPress = false;
            if (motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                isPress = true;
            }
            switch (view.getId()){
                case R.id.Add:
                    if (isPress){
                        mAdd.IsSelect(true);
                        mAdd.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(ADD);
                    }else {
                        mAdd.IsSelect(false);
                        mAdd.setTextColor(getResources().getColor(R.color.select));
                    }
                    break;
                case R.id.Sub:
                    if (isPress){
                        mSub.IsSelect(true);
                        mSub.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(SUB);
                    }else {
                        mSub.IsSelect(false);
                        mSub.setTextColor(getResources().getColor(R.color.select));
                    }
                   break;
                case R.id.Multiply:
                    if (isPress){
                        mMultiply.IsSelect(true);
                        mMultiply.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(MULTIPLY);
                    }else {
                        mMultiply.IsSelect(false);
                        mMultiply.setTextColor(getResources().getColor(R.color.select));
                    }
                    break;
                case R.id.Division:
                    if (isPress){
                        mDivision.IsSelect(true);
                        mDivision.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(DIVISION);
                    }else {
                        mDivision.IsSelect(false);
                        mDivision.setTextColor(getResources().getColor(R.color.select));
                    }
                    break;
                case R.id.Mod:
                    if (isPress){
                        mMod.IsSelect(true);
                        mMod.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(MOD);
                    }else {
                        mMod.IsSelect(false);
                        mMod.setTextColor(getResources().getColor(R.color.select));
                    }
                    break;
                case R.id.Equal:
                    if (isPress){
                        mEqual.IsSelect(true);
                        mEqual.setTextColor(getResources().getColor(R.color.normal));
                        StartOperation(EQUAL);
                        isReturn = true;
                    }else {
                        mEqual.IsSelect(false);
                        mEqual.setTextColor(getResources().getColor(R.color.select));
                    }
                    break;
            }
            return true;
        }
    }
    private void StartOperation(char symbol){
        char operator = operatorStack.pop();
        if (operator == EQUAL){
            operatorStack.push(symbol);
        } else if (operator == '#'){
            numStack.push(numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()));
            operatorStack.push(symbol);
            numBuilder.delete(0,numBuilder.length());
        }else {
            switch (operator){
                case ADD:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),ADD);
                    break;
                case SUB:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),SUB);
                    break;
                case MULTIPLY:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),MULTIPLY);
                    break;
                case DIVISION:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),DIVISION);
                    break;
                case MOD:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()),MOD);
                    break;
                case EQUAL:
                    EXEOperation(numStack.pop(),numBuilder.toString().isEmpty()?0:Double.parseDouble(numBuilder.toString()));
                    break;
            }
        }
    }
    private void EXEOperation(double front,double rear){
        char operator = operatorStack.pop();
        EXEOperation(front,rear,operator);
    }
    private void EXEOperation(double front,double rear,char operator) {
        double result = 0;
        String str;
        /**
         * 对连续点击运算符，而运算数字并未符合标准时进行判断
         * 例如：12+
         * 此时12和+分别进栈，此时若再点击运算符+，则无法进行运算，因为rear运算数为空*/
        switch (operator) {
            case ADD:
                result = front + rear;
                break;
            case SUB:
                result = front - rear;
                break;
            case MULTIPLY:
                result = front * rear;
                break;
            case DIVISION:
                result = front / rear;
                break;
            case MOD:
                result = front < rear ? front :front % rear;
                break;
        }
        numStack.push(result);
        if (isReturn){
            operatorStack.push(EQUAL);
        }else {
            operatorStack.push(operator);
            isReturn = false;
        }
        str = String.valueOf(result);
        //判断小数位之后是否有数字
        if (str.substring(str.indexOf('.') + 1, str.length() - 1).isEmpty()) {
            str = str.substring(0, str.indexOf('.'));
        }
        ResultBox.setText(str);
        //前运算符清空，为后运算符输入做准备
        numBuilder.delete(0,numBuilder.length());
    }
    private void PopStack(){
        while (numStack.isEmpty()){
            numStack.pop();
        }
        while (operatorStack.isEmpty()){
            operatorStack.pop();
        }
    }
}
